package org.colafries.admin.querybuilder.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.colafries.admin.entity.domain.CustomTable;
import org.colafries.admin.exceptions.ServiceException;
import org.colafries.admin.querybuilder.entity.AggFunctionContext;
import org.colafries.admin.querybuilder.entity.SqlBuildContext;
import org.colafries.common.enums.Flag;
import org.colafries.admin.entity.domain.QueryParam;
import org.colafries.admin.querybuilder.entity.SelectSqlSchema;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author colafries
 * @version v1.0
 * @ClassName BuilderUtil
 * @Description
 * @date Created in 2024/5/16
 **/
@Slf4j
public class SqlSegmentBuilderUtil {
    /**
     * <p>转换表达式  covert {fieldCode} -> fieldExpression</p>
     * eg. {90999009} + {8899495905}-> accept_num_c01 + accept_num_c02
     *
     * @param expression
     * @param fieldExpMap
     * @return java.lang.String
     * @author colafries
     * @Date 2024/5/11
     */
    public static String convertExpression(String expression, Map<String, String> fieldExpMap) {
        Pattern pattern = Pattern.compile("\\{([^\\}]+)\\}");
        Matcher matcher = pattern.matcher(expression);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            String key = matcher.group(1);
            String value = Optional.ofNullable(fieldExpMap.get(key))
                    .orElseThrow(() -> new ServiceException("表达式解析失败，" + key + "不存在"));
            matcher.appendReplacement(sb, value);
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 解析聚合函数表达式 COUNT({fieldCode}) --> ExpressionContext(operator:COUNT,arguments:{fieldCode})
     *
     * @param expression
     * @Author anning
     * @Date 2024/6/19
     */
    public static AggFunctionContext parseAggFunctionExp(String expression) {
        if (Strings.isNullOrEmpty(expression)) {
            return null;
        }
        String regex = "(\\w+)\\((\\{\\w+\\})\\)";
        // 创建Pattern对象
        Pattern pattern = Pattern.compile(regex);
        // 创建Matcher对象
        Matcher matcher = pattern.matcher(expression);

        if (matcher.find()) {
            // 提取操作符和数据
            String aggFunction = matcher.group(1);
            String columnExpression = matcher.group(2);
            return AggFunctionContext.builder()
                    .aggFunction(aggFunction).columnExpression(columnExpression).build();
        }
        return null;
    }

    /**
     * 构建measure表达式
     *
     * @param measure
     * @return java.lang.String
     * @author colafries
     * @Date 2024/5/16
     */
    public static String buildMeasureExpression(QueryParam.Measure measure, Map<String, String> fieldExpMap) {
        String expression = measure.getExpression();
        if (Flag.YES == measure.getCalculatedFlag()) {
            // calculated measure expression
            expression = SqlSegmentBuilderUtil.convertExpression(expression, fieldExpMap);
        } else {
            // not calculated measure expression
            expression = String.format("%s(`%s`.`%s`)", measure.getDefaultAggregator(), measure.getTableHash(), measure.getField());
        }
        return expression;
    }

    /**
     * 获取表达式中所有key值，{key}
     *
     * @param expression
     * @return java.util.List<java.lang.String>
     * @Author anning
     * @Date 2024/6/24
     */
    public static List<String> getExpKeyList(String expression) {
        List<String> keyList = Lists.newArrayList();
        // 定义正则表达式
        String regex = "\\{\\s*([^}]+?)\\s*}";
        // 创建Pattern对象
        Pattern pattern = Pattern.compile(regex);
        // 创建Matcher对象
        Matcher matcher = pattern.matcher(expression);
        // 查找并添加匹配的内容到List中
        while (matcher.find()) {
            keyList.add(matcher.group(1).trim());
        }
        return keyList;
    }

    /**
     * 判断给定的表达式是否为函数表达式
     * @param expression
     * @return boolean
     * @Author anning
     * @Date 2024/7/5
     */
    public static boolean getFunctionExpFlag(String expression){
        Pattern function_pattern = Pattern.compile(
                "^\\s*[a-zA-Z_][a-zA-Z0-9_]*\\s*\\(.*\\)\\s*$"
        );
        if (StringUtils.isEmpty(expression)) {
            return false;
        }
        Matcher matcher = function_pattern.matcher(expression);
        return matcher.matches();
    }

    /**
     * 根据SQL查询上下文构建SelectSqlSchema
     *
     * @param sqlBuildContext
     * @param customTables
     * @return org..colafries.common.model.metadata.SelectSqlSchema
     * @author colafries
     * @Date 2024/5/17
     */
    public static SelectSqlSchema buildSelectSqlSchema(SqlBuildContext sqlBuildContext, List<CustomTable> customTables) {
        // 构建select sql Schema
        SelectSqlSchema selectSqlSchema = new SelectSqlSchema();
        selectSqlSchema.setSelectColumn(CollectionUtil.join(sqlBuildContext.getSelectColumns(), ","));
        selectSqlSchema.setSelectTable(buildSelectTables(customTables));
        selectSqlSchema.setSelectCondition(CollectionUtil.join(sqlBuildContext.getWhereConditions(), " AND "));
        selectSqlSchema.setSelectGroupBy(CollectionUtil.join(sqlBuildContext.getGroupByColumns(), ","));
        selectSqlSchema.setSelectHaving(CollectionUtil.join(sqlBuildContext.getHavingConditions(), " AND "));
        selectSqlSchema.setSelectOrderBy(CollectionUtil.join(sqlBuildContext.getOrderByColumns(), ","));
        return selectSqlSchema;
    }

    /**
     * 构建 selectTables
     *
     * @param customTables
     * @return java.lang.String
     * @author colafries
     * @Date 2024/4/9
     */
    public static  String buildSelectTables(List<CustomTable> customTables) {
        List<String> selectSqlTables = customTables.stream().map(
                customTable -> {
                    // table
                    return "(" + customTable.getCustomSql() + ")" + " AS " + customTable.getTableHash();
                }
        ).collect(Collectors.toList());

        //TODO 后续增加多表逻辑
        return selectSqlTables.stream().findFirst().orElse(null);
    }

    /**
     * 根据SelectSqlSchema构建最终SQL
     *
     * @param selectSqlSchema
     * @return java.lang.String
     * @author colafries
     * @Date 2024/5/17
     */
    public static  String buildFinalSql(SelectSqlSchema selectSqlSchema) {
        StringBuilder modelSql = new StringBuilder(
                String.format("SELECT %s FROM %s WHERE 1=1 ", selectSqlSchema.getSelectColumn(), selectSqlSchema.getSelectTable())
        );

        if (!Strings.isNullOrEmpty(selectSqlSchema.getSelectCondition())) {
            modelSql.append(" AND ").append(selectSqlSchema.getSelectCondition());
        }
        if (!Strings.isNullOrEmpty(selectSqlSchema.getSelectGroupBy())) {
            modelSql.append(" GROUP BY ").append(selectSqlSchema.getSelectGroupBy());
        }
        if (!Strings.isNullOrEmpty(selectSqlSchema.getSelectHaving())) {
            modelSql.append(" HAVING (").append(selectSqlSchema.getSelectHaving()).append(")");
        }
        if (!Strings.isNullOrEmpty(selectSqlSchema.getSelectOrderBy())) {
            modelSql.append(" ORDER BY ").append(selectSqlSchema.getSelectOrderBy());
        }
        return modelSql.toString();
    }


}
